﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Common;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;

namespace ControleRepresentante.UnitTests
{
    public static class TestScenarioRepresentanteHelper
    {
        public static void DeleteRepresentante(this TestScenario testScenario, Guid representanteId)
        {
            IRepresentanteRepository representanteRepository = testScenario.RepositoryProvider.GetRepository<IRepresentanteRepository>();
            StatisticsBase statistics;
            int countBefore = representanteRepository.GetModels(out statistics).Count();
            using (RepresentanteController representanteController = new RepresentanteController(testScenario.RepositoryProvider, testScenario.AreaOperacaoRegistry, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider))
            {
                representanteController.Delete(representanteId);
                representanteController.Delete(representanteId, null);
                Assert.AreEqual(countBefore - 1, representanteRepository.GetModels(out statistics).Count());
            }
        }

        public static Guid CreateRepresentante(this TestScenario testScenario, string nome, bool ativo = true, params string[] users)
        {
            Representante representante = new Representante { Ativo = ativo, Nome = nome, UseJolitex = true, UseTrivium = true};
            IEnumerable<User> usersToAdd = users.Select(x => new MockUser(x));
            foreach (User userToAdd in usersToAdd)
            {
                representante.AddUser(userToAdd);
            }
            return testScenario.CreateRepresentante(representante);
        }

        private class MockUser : User
        {
            public MockUser(string username)
            {
                Username = username;
                Password = username;
            }
        }

        private static Guid CreateRepresentante(this TestScenario testScenario, Representante representante)
        {
            IRepresentanteRepository representanteRepository = testScenario.RepositoryProvider.GetRepository<IRepresentanteRepository>();
            StatisticsBase statistics;
            int countBefore = representanteRepository.GetModels(out statistics).Count();
            using (RepresentanteController representanteController = new RepresentanteController(testScenario.RepositoryProvider, testScenario.AreaOperacaoRegistry, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider))
            {
                representanteController.Create();
                foreach (User user in representante.Users)
                {
                    representanteController.UserInsert(user.Username, user.Password, user.Email, user.Ativo);
                }
                ActionResult actionResult = representanteController.Create(representante.Nome, representante.Ativo, representante.UseJolitex, representante.UseTrivium);
                IEnumerable<Representante> representantes = representanteRepository.GetModels(out statistics);
                Assert.AreEqual(countBefore + 1, representantes.Count());
                Representante addedRepresentante = representantes.FirstOrDefault(x => x.Nome == representante.Nome);
                Assert.AreEqual(representante.Nome, addedRepresentante.Nome);
                Assert.AreEqual(representante.Ativo, addedRepresentante.Ativo);
                Assert.AreEqual(representante.UseJolitex, addedRepresentante.UseJolitex);
                Assert.AreEqual(representante.Users.Count(), addedRepresentante.Users.Count());
                foreach (User user in representante.Users)
                {
                    User addedUser = addedRepresentante.Users.Single(x => x.Username == user.Username);
                    Assert.AreEqual(user.IsAdmin, addedUser.IsAdmin);
                    Assert.AreEqual(user.Password.Encrypt(), addedUser.Password);
                    Assert.AreEqual(user.Username, addedUser.Username);
                }
                Assert.IsInstanceOfType(actionResult, typeof (RedirectToRouteResult));
                RedirectToRouteResult redirectToRouteResult = (RedirectToRouteResult) actionResult;
                Assert.AreEqual("Details", redirectToRouteResult.RouteValues["action"]);
                Assert.AreEqual(addedRepresentante.Id, redirectToRouteResult.RouteValues["id"]);
                return addedRepresentante.Id;
            }
        }
    }
}